package com.learnosity.extendotext
{
	import com.learnosity.extendotext.StyleSheet;
	import flash.display.*;
	import flash.text.engine.*;
	import flash.utils.Dictionary;
			
	public class ExtendoText extends Sprite
	{
		private var textContent:String; //Raw text content
		private var xmlContent:XML; //Raw text content
		private var element:ContentElement;
		private var formating:ElementFormat;
		private var groupVector:Vector.<ContentElement>;	
		private var paragraphWidth:int;
		private var mapper:Dictionary;
		private var styleSheet:StyleSheet;
		
		public function ExtendoText(mapper:Dictionary,styleSheet:StyleSheet)
		{
			this.paragraphWidth = 200;
			this.formating =  new ElementFormat();
			var fontDescription:FontDescription = new FontDescription("Arial");
			formating.fontSize = 11;
			formating.fontDescription = fontDescription;
			
			this.mapper = mapper;
			this.styleSheet = styleSheet;
		}
		/**
		 * The XML formatted content for the textarea
		 */
		public function set text ( content:String ):void
		{
			XML.ignoreWhitespace = false;
			
			textContent = content;
			xmlContent = XML('<root>'+content+'</root>');
			
			render(this.xmlContent);
		}
		
		public function get text ():String
		{
			return textContent;
		}
		/**
		 * Parse the content and render it to the screen
		 */
		protected function render(xmlContent:XML):void
		{
			//Remove all current children
			while ( numChildren ) removeChildAt(0);	

			groupVector = new Vector.<ContentElement>();
			
			for each(var node:XML in xmlContent.*){
				var currentGroupVector:Vector.<ContentElement> = renderElement(node,this.formating);				

				for each (element in currentGroupVector)
				{
					groupVector.push(element);
				}	
			}
							
			var groupElement:GroupElement = new GroupElement(groupVector);
			var textBlock:TextBlock = new TextBlock();
			textBlock.content = groupElement;
			renderParagraph ( textBlock );		
		}
		
		/**
		 * 
		 */
		 protected function renderElement(node:XML,format:ElementFormat):Vector.<ContentElement>{
		 	var groupVector:Vector.<ContentElement> = new Vector.<ContentElement>();
		 	
		 	//Handle formatting object from style class
			var matched:Vector.<RuleSet> = styleSheet.findRules(node.name());
			var format:ElementFormat = styleSheet.getFormattingObject(matched,format);
			
		
			//Are we passing this into a custom class?		
			if(mapper[node.name()] != null)
			{
				//Create the new class to handle this item and add as graphic element	
				var item:DisplayObject = new mapper[node.name()](node) as DisplayObject;
				element = new GraphicElement(item, item.width,item.height,format);
				groupVector.push(element);
			}
			// Is it a simple text node
			else if(node.hasSimpleContent() || node.nodeKind() == 'text')
			{
				//Set the text if this a text node
				trace(node.name() +':'+ node.hasComplexContent());		
				element = new TextElement ( node.toString(), format );
				groupVector.push(element);
			}
			else
			{
				//Complex element so recursive call into this method
				for each(var subnode:XML in node.*){
					var currentGroupVector:Vector.<ContentElement>  = renderElement(subnode,format);	
					for each (element in currentGroupVector)
					{
						groupVector.push(element);
					}	
				}	
			}

			return groupVector;
		 }
		
		/**
		 * render a single line to the screen 
		 */
		protected function renderParagraph (textBlock:TextBlock):void 
		{
			var line:TextLine = textBlock.createTextLine (null, paragraphWidth);
			var yPos:int = 0;
			var lineHeight:int = 0;
			
			while (line)
			{
				addChild(line);
				line.x = 15;
				//Get line height of line
				if(line.hasGraphicElement){
					//Have a graphic so need to get atom data
					var atomCount:int = line.atomCount; 
					lineHeight = 0;
					for(var i:int = 0; i < atomCount; i++){
						var thisAtomHeight:int = line.getAtomBounds(i).height;
						if(thisAtomHeight > lineHeight) lineHeight = thisAtomHeight;
					}
					//Allow the atom data to be garbage collected
					line.flushAtomData();
				}
				else lineHeight = line.height;
				
				yPos += lineHeight+8;
				line.y = yPos;
				line = textBlock.createTextLine(line, paragraphWidth);
			}
		}
		
		

	}
}